using ESRI.ArcGIS.Geometry;
using GisSharpBlog.NetTopologySuite.IO;

namespace Spatial.Formats
{
    /// <summary>
    /// This class is used to convert a GeoAPI Geometry to ESRI and vice-versa.
    /// It can also convert a ESRI Geometry to WKB/WKT and vice-versa.
    /// </summary>
    /// <remarks>Copied wholesale from this forum post, then converted to
    /// non static class so that the <see cref="IGeometryFactory3"/> can
    /// be passed in from either a server or desktop application.</remarks>
    public class Converters
    {
        private readonly IGeometryFactory3 _geometryFactory;

        public Converters(IGeometryFactory3 geometryFactory)
        {
            _geometryFactory = geometryFactory;
        }

        public byte[] ConvertGeometryToWKB(IGeometry geometry)
        {
            var oper = (ITopologicalOperator) geometry;
            oper.Simplify();

            var b = _geometryFactory.CreateWkbVariantFromGeometry(geometry) as byte[];
            return b;
        }

        public byte[] ConvertWKTToWKB(string wkt)
        {
            var writer = new WKBWriter();
            var reader = new WKTReader();
            return writer.Write(reader.Read(wkt));
        }

        public string ConvertWKBToWKT(byte[] wkb)
        {
            var writer = new WKTWriter();
            var reader = new WKBReader();
            return writer.Write(reader.Read(wkb));
        }

        public string ConvertGeometryToWKT(IGeometry geometry)
        {
            byte[] b = ConvertGeometryToWKB(geometry);
            var reader = new WKBReader();
            GeoAPI.Geometries.IGeometry g = reader.Read(b);
            var writer = new WKTWriter();
            return writer.Write(g);
        }

        public IGeometry ConvertWKTToGeometry(string wkt)
        {
            byte[] wkb = ConvertWKTToWKB(wkt);
            return ConvertWKBToGeometry(wkb);
        }

        public IGeometry ConvertWKBToGeometry(byte[] wkb)
        {
            IGeometry geom;
            int countin = wkb.GetLength(0);
            _geometryFactory.CreateGeometryFromWkbVariant(wkb, out geom, out countin);
            return geom;
        }


        public IGeometry ConvertGeoAPIToESRI(GeoAPI.Geometries.IGeometry geometry)
        {
            var writer = new WKBWriter();
            byte[] bytes = writer.Write(geometry);
            return ConvertWKBToGeometry(bytes);
        }

        public GeoAPI.Geometries.IGeometry ConvertESRIToGeoAPI(IGeometry geometry)
        {
            byte[] wkb = ConvertGeometryToWKB(geometry);
            var reader = new WKBReader();
            return reader.Read(wkb);
        }
    }
}